package edu.spbsu.nonsm00th.qdiff.parser.word;

/**
 * Expression unit presentation class. Wrapper for words.
 *
 * @author mukhadin
 */
public class Unit {//TODO: add isFunction, isArgument, etc.

    /**
     * Default constructor.
     */
    public Unit(Word word, int position) {
        this.word = word;
        this.startPosition = position;
        this.argumentsCount = -1;
        if (word instanceof Operation) {
            Operation o = (Operation)word;
            if (Operation.DIVISION == o || Operation.EXPONENTIATION == o || Operation.MULTIPLICATION == o) {
                this.argumentsCount = 2;
            }
        }
        if (word instanceof Function) {
            Function f = (Function)word;
            if (Function.MAX == f || Function.MIN == f) {
                //do nothing
            } else if (Function.POWER == f || Function.LOG == f) {
                this.argumentsCount = 2;
            } else {
                this.argumentsCount = 1;
            }
        }
    }

    /** Wrapped word. */
    private Word word;

    /** Start position of the word in parsed expression. */
    private int startPosition;

    /** Word arguments count. Should be used only by operations and functions. */
    private int argumentsCount;

    public boolean isFunction() {
        return word instanceof Function;
    }

    public boolean isOperation() {
        return word instanceof Operation;
    }

    public boolean isNumber() {
        return word instanceof Number;
    }

    public boolean isControl() {
        return word instanceof Control;
    }

    public boolean isArgument() {
        return word instanceof Argument;
    }

    public int getStartPosition() {
        return startPosition;
    }

    public void setStartPosition(int startPosition) {
        this.startPosition = startPosition;
    }

    public Word getWord() {
        return word;
    }

    public void setWord(Word word) {
        this.word = word;
    }

    public int getArgumentsCount() {
        if (isFunction() || isOperation()) {
            if (-1 == argumentsCount) {
                throw new IllegalStateException("argumentsCount property was not set before. Maybe there is an error in a parser.");
            }
            return argumentsCount;
        } else {
            throw new IllegalStateException("argumentsCount property is available only for functions and operations.");
        }
    }

    public void setArgumentsCount(int argumentsCount) {
        if (isFunction() || isOperation()) {
            if (-1 == argumentsCount) {
                throw new IllegalStateException("argumentsCount property was already set before. Maybe there is an error in a parser.");
            }
            this.argumentsCount = argumentsCount;
        } else {
            throw new IllegalStateException("argumentsCount property is settable only for functions and operations.");
        }
    }

}
